﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Processing;
using Cloo;
using Processing.Structures;

namespace RayTracer.Kernels
{
    /// <summary>
    /// Schnittpunkt mit einem Objekt: Hierbei gilt es den Schnittpunkt und Einfallsrichtung
    /// eines Strahls mit einem spezifischen Objekt zu ermitteln. Wobei dieses Objekt
    /// verschiedene Typen haben kann.
    /// </summary>
    partial class KernelPrimitiveSphere : AKernelPrimitive
    {
        #region Attribute
        #region GPU
        private Buffer<float> gpu_objRadius;
        #endregion GPU
        #endregion Attribute

        #region Eigenschaften
        #region Dateninitialisierung
        /// <summary>
        /// Gibt und Setzt die Kugelradiusse.
        /// </summary>
        public Buffer<float> ObjectRadius { get { return gpu_objRadius; } set { gpu_objRadius = value; } }
        #endregion Dateninitialisierung

        #region Kernelausführung
        /// <summary>
        /// Gibt den Quellcode des Programms an.
        /// </summary>
        protected override string ProgramSource { get { return KERNEL_SOURCE; } }

        /// <summary>
        /// Gibt den Namen des Programms an.
        /// </summary>
        protected override string ProgramName { get { return KERNEL_MAIN; } }

        /// <summary>
        /// Gibt an ob die Kerneldaten valid initialisiert sind.
        /// </summary>
        protected override bool IsValidInitialized
        {
            get
            {
                if (gpu_objRadius == null) throw new RayTracerException("Die Objektradien müssen angegeben werden.");
                return base.IsValidInitialized &&
                    gpu_objPos.Length == gpu_objRadius.Length;
            }
        }
        #endregion Kernelausführung

        /// <summary>
        /// Gibt eine hochgegriffene Schätzung über die Anzahl der Bytes pro Pixel/Ray.
        /// </summary>
        public static int BytesPerPixel { get { return (7 * (sizeof(float) * 4)) + (2 * (sizeof(float) * 8)) + (3 * sizeof(float)); } }
        #endregion Eigenschaften

        #region Methoden
        /// <summary>
        /// Instanziiert und initialisiert die Kernel.
        /// </summary>
        /// <param name="processor">Der Prozessor.</param>
        public KernelPrimitiveSphere(Processor processor) : base(processor) { }

        /// <summary>
        /// Setzt die Daten in Kernelargumente fest.
        /// </summary>
        protected override void SetArguments()
        {
            SetArgument(0, gpu_rayPos);
            SetArgument(1, gpu_rayDir);
            SetArgument(2, gpu_lastDist);
            SetArgument(3, (int)(gpu_objPos.Length));
            SetArgument(4, gpu_objPos);
            SetArgument(5, gpu_objRot);
            SetArgument(6, gpu_objMat);
            SetArgument(7, gpu_objRadius);

            SetArgument(8, gpu_dist, true);
            SetArgument(9, gpu_mat);
            SetArgument(10, gpu_intersec);
            SetArgument(11, gpu_normal);
        }
        #endregion Methoden
    }
}
